/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package rejeev.tracer;

import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;

/**
 *
 * @author rejeev.divakaran
 */
public class TracerClassAdapter extends ClassAdapter {
    //private ClassVisitor cv;
    private boolean isInterface;
    private String owner;
    private int ACC_INTERFACE;
    private boolean exclude;
    //private Set<String> excludeList = new HashSet<String>();
    //private Set<String> includeList;
    
    public TracerClassAdapter(ClassVisitor cv){
        super(cv);
        this.cv = cv;
        /*
        excludeList.add("java/");
        excludeList.add("javax/");
        excludeList.add("sun/");
        excludeList.add("com/sun/");
        excludeList.add("org/xml/");
        excludeList.add("rejeev/tracer/");
        excludeList.add("org/omg/");
        excludeList.add("org/netbeans/");
        excludeList.add("org/apache/");
        excludeList.add("org/w3c/");
        excludeList.add("org/json/");
        excludeList.add("org/jcp/");
        excludeList.add("tools/com/sun/");
        */
    }
    
    @Override
    public void visit(int version, int access, String cName, String sign, String superName, String[] interfaces){
        try{
            cv.visit(version, access, cName, sign, superName, interfaces);
            this.owner = cName;
            isInterface = (access & ACC_INTERFACE) != 0;
            //System.out.println(cName);
            // to debug
            //exclude = true;
            //for debugging; some issue with Inner Class instrumentation
            /*
            if(cName.indexOf("$") >= 0) {
                exclude = true;
                return;
            }

            if(includeList != null){
                for(String pkg : includeList){
                    if(!cName.startsWith(pkg)){
                         exclude = true;
                         return;
                    }
                }
            }

            for(String pkg : excludeList){
                if(cName.startsWith(pkg)){
                    exclude = true;
                    return;
                }
            }
            */
            exclude = Configuration.getInstance().isToBeExcluded(cName);
            //if(!exclude) System.out.println("instrumenting class: " + cName);
            //else System.out.println("excluding the class: " + cName);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    
    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions){
        
        MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
        try{
            //System.out.println("-----------------");
            //System.out.println("className: " + owner);
            //System.out.println("exclude: " + exclude);
            //System.out.println("method: " + name);
            //System.out.println("+++++++++++++++++++++");
            if (!isInterface && !exclude && mv != null) {
                mv = new TracerMethodAdapter(owner, access, name, desc, mv);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return mv;
    }
    /*
    public void setExcludeList(Set<String> filter){
        excludeList = filter;
    }
    
    public void setIncludeList(Set<String> filter){
        includeList = filter;
    }
    */
}
